package com.wei.czz.framework.common.service;

import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.common.sms.SendSmsDto;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.framework.common.entity.SmsTemplateEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-14 14:05:18
 * className: SmsService
 * version: 1.0
 * description:
 */
public interface SmsService {

    Logger log = LoggerFactory.getLogger(SmsService.class);

    /**
     * 发送短信操作
     * @param mobile      接收手机号
     * @param smsTemplate 短信模板对象
     * @param paramMap    短信参数映射
     * @return 发送结果
     */
    SendSmsDto sendSms(String mobile, SmsTemplateEntity smsTemplate, Map<String, String> paramMap);

    /**
     * 批量发送短信操作
     * @param mobileList  接收手机号列表
     * @param smsTemplate 短信模板对象
     * @param paramMap    短信参数映射
     * @return 发送结果
     */
    SendSmsDto batchSendSms(List<String> mobileList, SmsTemplateEntity smsTemplate, Map<String, String> paramMap);

    /**
     * 获取短信渠道参数操作
     * @return 短信参数映射
     */
    Map<String, NameValue<String>> getChannelParam(String channelParam);

    /**
     * 校验短信参数
     * @param params   短信模板需要的参数字段，英文逗号分割
     * @param paramMap 参数映射
     */
    default void validParamMap(String params, Map<String, String> paramMap) {
        String[] paramArr = params.split(",");
        for (String param : paramArr) {
            if (Objects.isNull(paramMap.get(param))) {
                log.error("短信参数校验，短信模板占位符（{}）对应的值为空", param);
                throw new CzzException(ResultEnum.SMS_PARAM_FAIL);
            }
        }
    }

    /**
     * <p>
     * 构造短信内容
     * </p>
     * 替换短信模板中的占位符
     * <p><blockquote><pre>
     * content: 【{#type}验证码】：您正在进行短信登录，登录验证码：{#code}，请勿将验证码告知他人，防止财产损失
     * paramMap: {
     *   code：112266
     *   type：短信
     * }
     * return: 【短信验证码】：您正在进行短信登录，登录验证码：112266，请勿将验证码告知他人，防止财产损失
     * </pre></blockquote><p>
     * @param content   短信模板
     * @param paramMap  参数映射
     * @param highlight 模板值是否高亮显示[true-是 false-否]
     * @return 完整短信内容
     */
    default String buildContent(String content, Map<String, String> paramMap, boolean highlight) {
        // 结果集
        StringBuilder sb = new StringBuilder();

        String prefix = "{#";
        int prefixLength = prefix.length();
        int suffix = '}';

        // 字符串遍历初始下标
        int index = 0;

        int start;
        do {
            // 寻找开始占位符下标
            start = content.indexOf(prefix, index);
            if (start != -1) {
                // 寻找结束占位符下标（从开始占位符后面开始遍历）
                int end = content.indexOf(suffix, start);
                if (end != -1) {
                    // 添加’开始占位符’前面未添加过的字符串
                    sb.append(content, index, start);

                    // 占位符名称
                    String replaceKey = content.substring(start + prefixLength, end);

                    // 获取替换值
                    String val = paramMap.get(replaceKey);
                    if (Objects.isNull(val)) {
                        log.error("模板占位符（{}）对应的值为空", replaceKey);
                        throw new CzzException(ResultEnum.SMS_PARAM_FAIL);
                    }
                    if (highlight) {
                        sb.append("<span style=\"color:red;\" class=\"value-color\">");
                    }
                    // 添加替换值
                    sb.append(val);
                    if (highlight) {
                        sb.append("</span>");
                    }

                    // 更新遍历开始下标
                    index = end + 1;
                } else {
                    // 找到开始占位符，未找到结束占位符，则表示没有可替换的占位符，直接结束循环
                    start = -1;
                }
            }
        } while (start != -1);

        // 如果未遍历完字符串，则将未遍历过的字符添加到结果中
        sb.append(content, index, content.length());

        return sb.toString();
    }

    /**
     * <p>
     * 校验短信模板参数
     * </p>
     * 校验模板内容里的占位字符是否全部出现在配置的参数字段中，全部匹配到则满足条件，否则不满足
     * @param content  短信模板
     * @param paramSet 参数字段集合
     * @return 校验结果
     */
    default boolean validTemplateParams(String content, Set<String> paramSet) {
        // 结果集
        boolean result = true;

        String prefix = "{#";
        int prefixLength = prefix.length();
        int suffix = '}';

        // 字符串遍历初始下标
        int cursor = 0;

        int start;
        do {
            // 寻找开始占位符下标
            start = content.indexOf(prefix, cursor);
            if (start != -1) {
                // 寻找结束占位符下标（从开始占位符后面开始遍历）
                int end = content.indexOf(suffix, start);
                if (end != -1) {

                    // 占位符名称
                    String replaceKey = content.substring(start + prefixLength, end);
                    if (!paramSet.contains(replaceKey)) {
                        log.info("占位字段【{}】未在参数字段中出现。", replaceKey);
                        result = false;
                        break;
                    }

                    // 更新遍历开始下标
                    cursor = end + 1;
                } else {
                    // 找到开始占位符，未找到结束占位符，则表示没有可替换的占位符，直接结束循环
                    start = -1;
                    result = false;
                }
            }
        } while (start != -1);

        return result;
    }

}
